package catnet

import (
	"catlib/errors"
	"catlib/group"
)

// Conn 用户链接
type Conn interface {
	Read() (b []byte, err error)       // 读数据
	Write(b []byte) (n int, err error) // 写数据
}

// ConnCall  服务器通用回调
type ConnCall interface {
	Close() error                                        // 关闭服务器
	SetErrorCall(code errors.Code, value ...interface{}) // 错误代码回调
	ConnCall(conn group.Context) error                   // 业务上下文回调
}

// Config 链接配置
type Config struct {
	group group.Group // 调度
	pool  group.Pool  // 缓冲
	// 配置信息
	PoolNum  int // 缓冲数量
	GroupNum int // 携程数量
	// 服务器信息
	Network, Address string
	ConnCall         ConnCall // 服务器回调
}

// Close 关闭
func (config *Config) Close() {
	group.CloseGroup(config.group) // 关闭调度
	config.pool.Close()            // 关闭缓存
}

// init 配置初始化
func (config *Config) init(New func() interface{}) {
	config.group = group.NewGroup()
	config.group.Init(config.GroupNum)
	config.pool = group.NewPool(New)
	config.pool.Init(config.PoolNum)
}

// Net 网络接口
type Net interface {
	Listen(config *Config) error // 创建链接
	Close() error                // 关闭链接
}

/*
// ConnTCP TCP用户链接
type ConnTCP struct {
	T    int64
	Size int
	Data []byte
	Conn *net.TCPConn
}

// Write 发送数据
func (tcp *ConnTCP) Write(b []byte) (n int, err error) {
	tcp.T = Ts() // 设置时间
	n, err = tcp.Conn.Write(b)
	tcp.T = -1 // 标记读取完成
	return n, err
}

// Read 读取数据
func (tcp *ConnTCP) Read() (_ []byte, err error) {
	tcp.T = Ts() // 设置时间
	tcp.Size, err = tcp.Conn.Read(tcp.Data[0:])
	tcp.T = -1 // 标记读取完成
	return tcp.Data[:tcp.Size], err
}

// Close 关闭链接
func (tcp *ConnTCP) Close() error {
	return tcp.Conn.Close()
}

// ConnUDP UDP用户链接
type ConnUDP struct {
	Size int
	Data []byte
	Add  *net.UDPAddr
	Conn *net.UDPConn
}

// Write 发送数据
func (udp *ConnUDP) Write(b []byte) (n int, err error) {
	return udp.Conn.WriteTo(b, udp.Add)
}

// Read 读取数据
func (udp *ConnUDP) Read() (_ []byte, err error) {
	return udp.Data[:udp.Size], nil
}

// Close 关闭链接
func (udp *ConnUDP) Close() error {
	return nil
}

/*
// Net 网络链接
type Net struct {
	GoSize  int  // 携程大小
	IsClose bool // 是否关闭
	IsError func(e error)
}

// newPool 创建对象池
func (listen *Net) newPool(New func() interface{}) *Pool {
	// 错误拦截
	e := make(chan interface{})
	go func() {
		listen.IsError((<-e).(error))
	}()
	// 创建池
	pool := &Pool{New: New}
	pool.Init(listen.GoSize)
	return pool
}

// newGroup 创建携程池
func (listen *Net) newGroup() *Group {
	// 错误拦截
	e := make(chan interface{})
	go func() {
		listen.IsError((<-e).(error))
	}()
	// 创建池
	group := &Group{}
	group.New(listen.GoSize, e)
	// 超时控制
	go func() {
		i := 0
		ts := int64(0)
		tk := time.NewTicker(time.Second)
		Tlist := make([]int64, listen.GoSize)
		for range tk.C {
			if !listen.IsClose {
				return
			}
			i = 0
			ts = Ts()
			group.ForEach(func(t int64, in interface{}) {
				Tlist[i] = (ts - t) / int64(time.Second)
				i++
			})
			if i != 0 {
				fmt.Println("周期打点:", Tlist[:i])
			}
		}
	}()
	return group
}

// ListenTCP 创建 TCP 服务器
func (listen *Net) ListenTCP(network, address string, call func(conn Conn)) (err error) {
	// 创建服务器
	defer isRecover(&err)
	add, err := net.ResolveTCPAddr(network, address)
	isError(err)
	tcp, err := net.ListenTCP(network, add)
	isError(err)
	defer tcp.Close()
	// 创建创建对象池
	pool := listen.newPool(func() interface{} {
		return &ConnTCP{Data: make([]byte, 256), T: -1}
	})
	defer pool.Close()
	// 创建携程池
	group := listen.newGroup()
	defer group.Close()
	// 处理链接
	listen.IsClose = true
	for listen.IsClose {
		// 从池得到对象
		p := pool.Get()
		conn := (p.Value).(*ConnTCP)
		// 得到链接
		conn.T = -1 // 标记超时没有生效
		conn.Conn, err = tcp.AcceptTCP()
		if err != nil {
			p.Put() // 放回
			listen.IsError(err)
		} else {
			// 携程处理
			group.Go(func(in interface{}) {
				// 池对象放回去
				pool := in.(*PoolData)
				defer pool.Put()
				// 用户代码处理
				call(pool.Value.(Conn))
			}, p)
		}
	}
	return err
}

// ListenUDP 创建 UDP 服务器
func (listen *Net) ListenUDP(network, address string, call func(conn Conn)) (err error) {
	// 创建服务器
	defer isRecover(&err)
	add, err := net.ResolveUDPAddr(network, address)
	isError(err)
	udp, err := net.ListenUDP(network, add)
	isError(err)
	defer udp.Close()
	// 创建创建对象池
	pool := listen.newPool(func() interface{} {
		return &ConnUDP{Data: make([]byte, 256)}
	})
	defer pool.Close()
	// 创建携程池
	group := listen.newGroup()
	defer group.Close()
	// 处理链接
	listen.IsClose = true
	for listen.IsClose {
		// 从池得到对象
		p := pool.Get()
		conn := (p.Value).(*ConnUDP)
		// 读数据
		conn.Size, conn.Add, err = udp.ReadFromUDP(conn.Data[0:])
		if err != io.EOF {
			p.Put() // 放回
			listen.IsError(err)
		} else {
			// 处理
			group.Go(func(in interface{}) {
				// 池对象放回去
				pool := in.(*PoolData)
				defer pool.Put()
				// 用户代码处理
				call(pool.Value.(Conn))
			}, p)
		}
	}
	return err
}
*/

// 错误处理
var isError = func(e error) {
	if e != nil {
		panic(e)
	}
}
var isRecover = func(e *error) {
	if err := recover(); err != nil {
		(*e) = err.(error)
	}
}
